using System;
using System.Collections.Generic;

namespace Skywalker.Fluently
{
    public abstract class Builder<TComponent, TBuilder> : IBuilder<TComponent>
        where TComponent : new()
        where TBuilder : Builder<TComponent, TBuilder>
    {
        object IBuilder.Component
        {
            get { return Component; }
        }

        public TComponent Component { get; private set; }

        protected Builder()
        {
            Component = new TComponent();
        }

        protected TBuilder SetProperty(Action<TComponent> setter)
        {
            setter(Component);
            return (TBuilder)this;
        }

        protected TBuilder AddItem<T>(Func<TComponent, IList<T>> list, T item)
        {
            var l = list(Component);

            if(l == null)
                throw new NullReferenceException("The returned list was null, which is not allowed");

            l.Add(item);
            return (TBuilder)this;
        }

        protected TBuilder AddItem<T, TItemBuilder>(Func<TComponent, IList<T>> list, Action<TItemBuilder> item) where TItemBuilder : IBuilder<T>, new()
        {
            return AddItem(list, CreateAndExecuteBuilder(item).Component);
        }

        protected T CreateBuilder<T>() where T : IBuilder, new()
        {
            return Factory.Default.CreateBuilder<T>();
        }

        protected T ExecuteBuilder<T>(T builder, Action<T> setup) where T : IBuilder, new()
        {
            return Factory.Default.ExecuteBuilder(builder, setup);
        }

        protected T CreateAndExecuteBuilder<T>(Action<T> setup) where T : IBuilder, new()
        {
            var builder = CreateBuilder<T>();

            if (setup != null)
                setup(builder);

            return builder;
        }
    }
}